Case Study: Hedging A Long-Only SPX Portfolio With Costless Collars

Case Study: Hedging A Long-Only SPX Portfolio With Costless Collars#

import pandas as pd
import numpy as np
import requests
import json
import os
from dotenv import load_dotenv
import config
import datetime
pd.set_option('display.max_columns', None)
from pandas.tseries.offsets import MonthEnd, MonthBegin


from pathlib import Path
import time
import io

import plotly.express as px
import plotly.graph_objects as go
import plotly.io as pio
pio.templates.default = "plotly_white"


from scipy.interpolate import griddata
from scipy.ndimage import gaussian_filter
import warnings
warnings.filterwarnings('ignore')
from scipy.stats import norm

from plotly.subplots import make_subplots


# import hedging functions
import spx_hedging_functions as hf
import importlib

/Users/jbejarano/GitRepositories/finm-32900-ALL/case_study_options/_output /Users/jbejarano/GitRepositories/finm-32900-ALL/case_study_options/_data jmbejara 2022-01-01 00:00:00 2023-12-31 00:00:00

# Load environment variables
DATA_DIR=Path(config.DATA_DIR)
OUTPUT_DIR=Path(config.OUTPUT_DIR)
WRDS_USERNAME=config.WRDS_USERNAME

START_DATE=config.START_DATE
END_DATE=config.END_DATE

asof_date = '2023-08-02'
interpolation_args = {'method':'cubic', 'order': 3}
# enter the range of costless collar to construct
d = 0.80
contracts_to_display = 15
r = 0.045
N = 1000
days_in_year = 365.

strike_range = (1000,6000)
expiry_range = (0.01, 2.0)

dt = 1/days_in_year



option_chain = hf.get_option_chain(asof_date=asof_date, startDate=START_DATE, endDate=END_DATE)
# display(option_chain)
# do we need to check if forward prices for calls and puts are the same? no, because the sql_query() function is pulling the forward price from a single other dataset and joining tables 


pareto_chart, delta_map, prediction_range = hf.run_prediction_models(ticker='SPX', option_chain=option_chain, asof_date=asof_date,
                                                                     contracts_to_display=contracts_to_display, heatmap_step=3, interpolation_args=interpolation_args) 

# get the forward prices
fwd_prices = hf.get_fwd_prices(asof_date, option_chain, contracts_to_display)

iv_surface, price_surface = hf.build_iv_and_price_surface(option_chain,
                                                          fwd_prices,
                                                          asof_date,
                                                          strike_range,
                                                          expiry_range,
                                                          smoothing=True,
                                                          smoothing_params={'sigma': 2, 'clip_bounds': (0.05, 0.75)},
                                                          )

hf.plot_vol_price_charts(iv_surface=iv_surface,
                        price_surface=price_surface,
                        strike_range=[np.floor(iv_surface.index.min()),np.ceil(iv_surface.index.max())],
                        expiry_range=[iv_surface.columns.min(), iv_surface.columns.max()],
                        iv_surface_title='SPX Implied Volatility',
                        price_surface_title='Price Surface as of ' + asof_date,)



default_percentiles = np.unique(np.round(np.sort(np.append(np.arange(0.1, 1.0, 0.1), np.array([d, 1-d]))),3))

print(f'Constructing a {d:.0%} / {(1-d):.0%} collar...')

# build the delta map
delta_map = hf.build_delta_map(option_chain, asof_date, contracts_to_display, show_detail=False, weighted=False,
                               interpolate_missing=True, interpolation_args=interpolation_args)


# simulate a range of futures, including the collar strike %iles    
simulated_futures = hf.simulate_futures(asof_date, fwd_prices, iv_surface, r, N, dt, default_percentiles, show_charts=True)

# convert delta map columns from date to time remaining to expiry, and match expiries of simulated futures
delta_map.columns = hf.dates_to_time_remaining(delta_map.columns, asof_date)
delta_map = delta_map.loc[:, simulated_futures.index]

collar_strikes, costless_collars  = hf.show_collar_strikes(d, delta_map, simulated_futures=simulated_futures, contracts_to_display=contracts_to_display, 
                                                           asof_date=asof_date, option_chain=option_chain)
>> Loading Data from OptionMetrics between 2022-01-01 00:00:00 and 2023-12-31 00:00:00
>> Saving to /Users/jbejarano/GitRepositories/finm-32900-ALL/case_study_options/_data/external/spx_options_2022-01_2023-12.parquet
>> Reading from file: /Users/jbejarano/GitRepositories/finm-32900-ALL/case_study_options/_data/external/spx_options_2022-01_2023-12.parquet
Loading Data took 0.21 seconds
Expiration Date 2023-08-03 2023-08-04 2023-08-07 2023-08-08 2023-08-09 2023-08-10 2023-08-11 2023-08-14 2023-08-15 2023-08-16 2023-08-17 2023-08-18 2023-08-21 2023-08-22 2023-08-23
80% Below 4545.00 4560.00 4560.00 4565.00 4570.00 4580.00 4585.00 4595.00 4600.00 4605.00 4605.00 4610.00 4620.00 4625.00 4625.00
50/50 4515.00 4515.00 4515.00 4520.00 4520.00 4520.00 4520.00 4520.00 4520.00 4525.00 4525.00 4525.00 4525.00 4525.00 4530.00
80% Above 4475.00 4460.00 4455.00 4450.00 4440.00 4430.00 4425.00 4420.00 4415.00 4410.00 4405.00 4400.00 4395.00 4395.00 4390.00
Fwd Prices 2023-08-02 4513.99 4514.59 4516.40 4517.01 4517.61 4518.21 4518.81 4520.64 4521.25 4521.86 4522.47 4523.09 4524.94 4525.56 4526.18
Expiration Date 2023-08-03 2023-08-04 2023-08-07 2023-08-08 2023-08-09 2023-08-10 2023-08-11 2023-08-14 2023-08-15 2023-08-16 2023-08-17 2023-08-18 2023-08-21 2023-08-22 2023-08-23
Price >=                              
$4,615.00 1% 2% 4% 7% 8% 11% 7% 12% 14% 16% 17% 19% 21% 22% 23%
$4,600.00 1% 4% 8% 10% 12% 10% 14% 17% 19% 21% 22% 24% 26% 27% 28%
$4,585.00 2% 8% 12% 9% 13% 17% 20% 23% 25% 26% 28% 29% 30% 31% 32%
$4,570.00 5% 14% 13% 18% 21% 25% 27% 29% 31% 32% 33% 34% 36% 36% 37%
$4,555.00 12% 14% 24% 27% 29% 32% 34% 36% 37% 38% 39% 39% 41% 41% 42%
$4,540.00 24% 29% 34% 36% 38% 40% 41% 42% 43% 44% 44% 45% 46% 46% 46%
$4,525.00 36% 42% 45% 46% 46% 47% 48% 49% 49% 49% 50% 50% 51% 51% 51%
$4,510.00 55% 54% 54% 54% 54% 54% 54% 55% 55% 55% 55% 55% 55% 55% 55%
$4,495.00 69% 64% 63% 62% 62% 61% 60% 60% 60% 60% 59% 59% 59% 59% 59%
$4,480.00 79% 72% 71% 69% 68% 66% 65% 65% 65% 64% 64% 64% 64% 63% 63%
$4,465.00 85% 79% 77% 75% 73% 71% 70% 70% 69% 68% 68% 67% 67% 67% 66%
$4,450.00 88% 83% 81% 79% 78% 76% 74% 74% 73% 72% 71% 71% 71% 70% 70%
$4,435.00 90% 87% 85% 83% 82% 79% 78% 77% 76% 75% 75% 74% 74% 73% 73%
$4,420.00 91% 89% 88% 86% 85% 82% 81% 80% 79% 78% 77% 77% 76% 76% 75%
$4,405.00 92% 91% 90% 88% 87% 85% 83% 83% 82% 81% 80% 79% 79% 78% 78%
$4,390.00 93% 92% 91% 90% 89% 87% 86% 85% 84% 83% 82% 81% 81% 80% 80%
$4,375.00 94% 93% 92% 91% 91% 88% 87% 87% 86% 85% 84% 83% 83% 82% 82%
$4,360.00 94% 93% 93% 92% 92% 90% 89% 88% 87% 87% 86% 85% 85% 84% 83%
$4,345.00 94% 94% 94% 93% 93% 91% 90% 90% 89% 88% 87% 87% 86% 85% 85%
$4,330.00 95% 94% 94% 94% 93% 92% 91% 91% 90% 89% 88% 88% 87% 87% 86%
$4,315.00 95% 95% 95% 94% 94% 93% 92% 92% 91% 90% 90% 89% 89% 88% 88%
$4,300.00 95% 95% 95% 95% 94% 93% 93% 92% 92% 91% 90% 90% 90% 89% 89%
$4,285.00 96% 95% 95% 95% 95% 94% 93% 93% 93% 92% 91% 91% 91% 90% 90%
$4,270.00 96% 96% 96% 95% 95% 94% 94% 94% 93% 93% 92% 92% 91% 91% 90%
$4,255.00 96% 96% 96% 96% 95% 94% 94% 94% 94% 93% 93% 92% 92% 92% 91%
$4,240.00 96% 96% 96% 96% 96% 95% 95% 95% 94% 94% 93% 93% 93% 92% 92%
$4,225.00 96% 96% 96% 96% 96% 95% 95% 95% 95% 94% 94% 93% 93% 93% 93%
$4,210.00 96% 96% 97% 96% 96% 95% 95% 95% 95% 95% 94% 94% 94% 93% 93%
$4,195.00 97% 96% 97% 97% 96% 96% 95% 96% 95% 95% 95% 94% 94% 94% 94%
$4,180.00 97% 97% 97% 97% 96% 96% 96% 96% 96% 95% 95% 95% 95% 94% 94%
$4,165.00 97% 97% 97% 97% 97% 96% 96% 96% 96% 96% 95% 95% 95% 95% 94%
$4,150.00 97% 97% 97% 97% 97% 96% 96% 96% 96% 96% 95% 95% 95% 95% 95%
$4,135.00 97% 97% 97% 97% 97% 96% 96% 96% 96% 96% 96% 96% 96% 95% 95%
$4,120.00 97% 97% 97% 97% 97% 96% 96% 97% 96% 96% 96% 96% 96% 96% 95%
$4,100.00 97% 97% 97% 97% 97% 97% 97% 97% 97% 97% 96% 96% 96% 96% 96%
$4,075.00 97% 97% 98% 97% 97% 97% 97% 97% 97% 97% 96% 96% 96% 96% 96%
$4,050.00 97% 97% 98% 98% 98% 97% 97% 97% 97% 97% 97% 97% 97% 97% 96%
$4,025.00 98% 98% 98% 98% 98% 97% 97% 97% 97% 97% 97% 97% 97% 97% 97%
$4,000.00 98% 98% 98% 98% 98% 97% 97% 98% 97% 97% 97% 97% 97% 97% 97%
$3,975.00 98% 98% 98% 98% 98% 97% 97% 98% 98% 98% 97% 97% 97% 97% 97%
$3,950.00 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 97% 97% 98% 97% 97%
$3,925.00 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98%
$3,900.00 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98%
$3,875.00 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98%
$3,850.00 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98%
$3,825.00 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98%
$3,800.00 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98%
$3,775.00 98% 98% 99% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98% 98%
$3,750.00 98% 98% 99% 99% 99% 98% 98% 98% 99% 99% 98% 98% 99% 98% 98%
$3,725.00 98% 98% 99% 99% 99% 98% 98% 98% 99% 99% 98% 98% 99% 99% 99%
$3,700.00 98% 98% 99% 99% 99% 98% 98% 98% 99% 99% 99% 99% 99% 99% 99%
$3,675.00 98% 99% 99% 99% 99% 98% 98% 99% 99% 99% 99% 98% 99% 99% 99%
$3,650.00 98% 99% 99% 99% 99% 99% 98% 99% 99% 99% 99% 99% 99% 99% 99%
$3,625.00 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99%
$3,600.00 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99%
$3,575.00 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99%
$3,550.00 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99%
$3,525.00 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99%
$3,500.00 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99%
$3,450.00 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99%
$3,375.00 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99%
$3,300.00 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99%
$3,225.00 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99% 99%
Constructing a 80% / 20% collar...
  2023-08-07 2023-08-08 2023-08-09 2023-08-10 2023-08-11 2023-08-14 2023-08-15 2023-08-16 2023-08-17 2023-08-18 2023-08-21 2023-08-22
10% 4449.50 4450.67 4438.45 4428.40 4421.81 4413.16 4403.29 4400.49 4400.64 4390.03 4385.70 4379.96
20% 4474.00 4475.09 4467.02 4465.16 4458.16 4453.21 4451.22 4453.14 4453.47 4443.70 4443.11 4438.91
30% 4492.66 4493.71 4490.18 4487.57 4486.09 4484.65 4485.24 4485.20 4485.94 4484.93 4485.61 4481.93
40% 4506.44 4507.57 4509.32 4506.90 4512.25 4511.35 4515.92 4514.30 4515.03 4514.33 4519.59 4514.84
50% 4521.48 4521.89 4528.31 4525.12 4530.28 4532.85 4539.55 4538.36 4539.39 4541.23 4549.80 4551.05
60% 4537.04 4537.69 4544.16 4543.29 4548.85 4559.11 4564.88 4566.87 4567.77 4570.09 4576.72 4578.88
70% 4554.38 4554.53 4561.46 4566.46 4570.92 4583.42 4590.72 4596.62 4597.01 4604.42 4613.82 4611.78
80% 4572.37 4572.06 4585.45 4594.78 4596.27 4611.94 4623.78 4631.76 4632.83 4640.59 4654.08 4652.53
90% 4599.37 4598.36 4613.98 4619.32 4627.56 4648.92 4664.74 4675.08 4676.60 4682.99 4703.57 4709.62
Strip 2023-08-02 4516.40 4517.01 4517.61 4518.21 4518.81 4520.64 4521.25 4521.86 4522.47 4523.09 4524.94 4525.56
  2023-08-07 2023-08-08 2023-08-09 2023-08-10 2023-08-11 2023-08-14 2023-08-15 2023-08-16 2023-08-17 2023-08-18 2023-08-21 2023-08-22
80% Above 4455.00 4450.00 4440.00 4430.00 4425.00 4420.00 4415.00 4410.00 4405.00 4400.00 4395.00 4395.00
80% Below 4560.00 4565.00 4570.00 4580.00 4585.00 4595.00 4600.00 4605.00 4605.00 4610.00 4620.00 4625.00
Sim. 80% Below 4572.37 4572.06 4585.45 4594.78 4596.27 4611.94 4623.78 4631.76 4632.83 4640.59 4654.08 4652.53
Sim. 80% Above 4474.00 4475.09 4467.02 4465.16 4458.16 4453.21 4451.22 4453.14 4453.47 4443.70 4443.11 4438.91
Strip 2023-08-02 4516.40 4517.01 4517.61 4518.21 4518.81 4520.64 4521.25 4521.86 4522.47 4523.09 4524.94 4525.56
Costless Ceiling 4750.00 4630.00 4615.00 4620.00 4620.00 4625.00 4620.00 4620.00 4620.00 4620.00 4620.00 4620.00
Net cost to hedge this set of collars: $-0.3750 per unit